001 /** 002 * Java Gui Builder - A library to build GUIs using an XML file. 003 * Copyright 2002, 2003 (C) François Beausoleil 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library; if not, write to the Free Software 017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018 */ 019 020 package jgb.handlers.swing; 021 022 import jgb.builder.TagHandler; 023 import jgb.builder.utils.CurrentObjectsStackManager; 024 import org.xml.sax.Locator; 025 import org.xml.sax.SAXException; 026 import org.xml.sax.SAXParseException; 027 028 import java.awt.*; 029 import java.util.Map; 030 031 032 /** 033 * Default implementation for {@link jgb.builder.TagHandler TagHandler}. 034 * This default implementation does not allow subclasses to override 035 * {@link #startElement(java.lang.String, java.util.Map, java.util.Map) startElement(String, Map, Map)} 036 * or {@link #endElement(java.lang.String, java.util.Map) endElement(String, Map)}. It provides equivalent 037 * methods in the form of {@link #enterElement(java.util.Map) enterElement(Map)} 038 * and {@link #exitElement() exitElement()}.<p> 039 * This class also provides many helpful methods: 040 * <ul> 041 * <li> 042 * {@link #getObject(java.lang.String) getObject(String)} and 043 * {@link #putObject(java.lang.String, java.lang.Object) putObject(String, Object)}<br /> 044 * Return or update an object in the context based on the object's id. Uses 045 * the key {@link jgb.builder.TagHandler#OBJECTS_MAP_KEY TagHandler.OBJECTS_MAP_KEY} 046 * </li> 047 * <li> 048 * {@link #pushCurrentObject(java.lang.String, java.lang.Object) pushCurrentObject(String, Object)} 049 * and {@link #popCurrentObject() popCurrentObject()}<br /> 050 * Push or pop the current object from the current objects stack. Uses the key 051 * {@link jgb.builder.TagHandler#CURRENT_OBJECTS_STACK_KEY TagHandler.CURRENT_OBJECTS_STACK_KEY} 052 * </li> 053 * </ul> 054 * @see jgb.builder.utils.CurrentObjectsStackManager CurrentObjectsStackManager 055 * - Manage a stack of objects 056 * @since 0.1a 057 * @author Francois Beausoleil, <a href="mailto:fbos@users.sourceforge.net">fbos@users.sourceforge.net</a> 058 */ 059 public abstract class AbstractTagHandler implements TagHandler { 060 /** 061 * The name of the id attribute. 062 */ 063 protected static final String ATTR_ID = "id"; 064 065 /** 066 * The name of the class attribute. 067 */ 068 protected static final String ATTR_CLASS = "class"; 069 070 /** 071 * The name of the refid attribute. 072 */ 073 protected static final String ATTR_REFID = "refid"; 074 075 protected String tagName; 076 protected Map tagContext; 077 078 public final void startElement(String qName, Map tagContext, Map atts) throws SAXException { 079 this.tagContext = tagContext; 080 this.tagName = qName; 081 082 try { 083 enterElement(atts); 084 } catch (SAXException e) { 085 throw e; 086 } catch (Exception e) { 087 e.printStackTrace(); 088 throwParsingException("Unhandled exception while entering element" + qName, e); 089 } finally { 090 this.tagContext = null; 091 this.tagName = null; 092 } 093 } 094 095 public final void endElement(String qName, Map tagContext) throws SAXException { 096 this.tagContext = tagContext; 097 this.tagName = qName; 098 099 try { 100 exitElement(); 101 } catch (SAXException e) { 102 throw e; 103 } catch (Exception e) { 104 throwParsingException("Unhandled exception while exiting element " + qName, e); 105 } finally { 106 this.tagContext = null; 107 this.tagName = null; 108 } 109 } 110 111 protected Object getObject(String id) { 112 Map objectsMap = (Map)tagContext.get(TagHandler.OBJECTS_MAP_KEY); 113 return objectsMap.get(id); 114 } 115 116 protected void putComponent(String id, Component component) { 117 putObject(id, component); 118 } 119 120 protected void putObject(String id, Object value) { 121 Map objectsMap = (Map)tagContext.get(TagHandler.OBJECTS_MAP_KEY); 122 objectsMap.put(id, value); 123 } 124 125 protected void pushCurrentObject(Object o) { 126 pushCurrentObject(null, o); 127 } 128 129 /** 130 * Pushes the passed object and id to the current objects stack. 131 */ 132 protected void pushCurrentObject(String id, Object o) { 133 getCurrentObjectsStack().pushCurrentObject(o, id); 134 updateCurrentObject(); 135 } 136 137 protected void popCurrentObject() { 138 getCurrentObjectsStack().popCurrentObject(); 139 updateCurrentObject(); 140 } 141 142 protected Object getCurrentObject() { 143 return getCurrentObjectsStack().getCurrentObject(); 144 } 145 146 protected String getCurrentObjectId() { 147 return getCurrentObjectsStack().getCurrentObjectId(); 148 } 149 150 protected boolean isCurrentObjectValid() { 151 return getCurrentObjectsStack().isCurrentObjectValid(); 152 } 153 154 protected void throwParsingException(String msg) throws SAXException { 155 throwParsingException(msg, null); 156 } 157 158 protected void throwParsingException(Exception cause) throws SAXException { 159 throwParsingException(null, cause); 160 } 161 162 /** 163 * Throw a {@link org.xml.sax.SAXException} or a subclass if a locator is 164 * available. 165 */ 166 protected void throwParsingException(String msg, Exception cause) throws SAXException { 167 Locator locator = (Locator)tagContext.get(TagHandler.DOCUMENT_LOCATOR_KEY); 168 if (locator == null) { 169 throw new SAXException(msg + " tag " + tagName, cause); 170 } else { 171 throw new SAXParseException(msg + " tag " + tagName, locator, cause); 172 } 173 } 174 175 /** 176 * Actually handle the element's behaviour when the element's start 177 * is encountered. 178 */ 179 protected abstract void enterElement(Map atts) throws SAXException; 180 181 /** 182 * Actually handle the element's behaviour when the element's closure 183 * is encountered. 184 */ 185 protected abstract void exitElement() throws SAXException; 186 187 private CurrentObjectsStackManager getCurrentObjectsStack() { 188 CurrentObjectsStackManager stackManager = 189 (CurrentObjectsStackManager)tagContext.get(TagHandler.CURRENT_OBJECTS_STACK_KEY); 190 if (stackManager == null) { 191 stackManager = new CurrentObjectsStackManager(); 192 tagContext.put(TagHandler.CURRENT_OBJECTS_STACK_KEY, stackManager); 193 } 194 195 return stackManager; 196 } 197 198 private void updateCurrentObject() { 199 tagContext.remove(TagHandler.CURRENT_OBJECT_KEY); 200 tagContext.remove(TagHandler.CURRENT_OBJECT_ID_KEY); 201 202 if (isCurrentObjectValid()) { 203 tagContext.put(TagHandler.CURRENT_OBJECT_KEY, getCurrentObject()); 204 String objectId = getCurrentObjectId(); 205 if (objectId != null) { 206 tagContext.put(TagHandler.CURRENT_OBJECT_ID_KEY, objectId); 207 } 208 } 209 } 210 }